package com.warom.sdg.repository;

import android.content.Context;
import android.util.Log;


import com.warom.sdg.dao.PlcDataDao;
import com.warom.sdg.database.SdgDatabase;
import com.warom.sdg.model.PlcDataEntity;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;

/**
 * PLC数据仓库类
 * 提供数据库操作的高级接口，管理PlcDataDao实例
 */
public class PlcDataRepository {
    private static final String TAG = "PlcDataRepository";
    
    // 数据库和DAO
    private final SdgDatabase database;
    private final PlcDataDao plcDataDao;
    
    // 线程池执行器，用于异步操作
    private final ExecutorService executor;
    
    /**
     * 构造函数
     * @param context 上下文
     */
    public PlcDataRepository(Context context) {
        database = SdgDatabase.getInstance(context);
        plcDataDao = database.getPlcDataDao();
        executor = Executors.newFixedThreadPool(4); // 创建线程池
    }
    
    /**
     * 插入一条PLC数据记录
     * @param data PLC数据实体
     * @param onComplete 操作完成回调
     * @param onError 错误回调
     */
    public void insert(final PlcDataEntity data, Runnable onComplete, Consumer<String> onError) {
        Log.d(TAG, "插入数据: " + data.toString());
        executor.execute(() -> {
            try {
                long id = plcDataDao.insert(data);
                Log.d(TAG, "数据插入成功，ID: " + id);
                if (onComplete != null) {
                    onComplete.run();
                }
            } catch (Exception e) {
                String errorMsg = "数据插入失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (onError != null) {
                    onError.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 插入一条PLC数据记录（无回调）
     * @param data PLC数据实体
     */
    public void insert(final PlcDataEntity data) {
        insert(data, null, null);
    }
    
    /**
     * 获取所有PLC数据
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getAllData(Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getAllData();
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取所有数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定设备的所有PLC数据
     * @param deviceId 设备ID
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getDataByDeviceId(final int deviceId, Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getDataByDeviceId(deviceId);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取指定设备数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定名称的PLC数据
     * @param name 数据点名称
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getDataByName(final String name, Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getDataByName(name);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取指定名称数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定地址的PLC数据
     * @param address Modbus地址
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getDataByAddress(final String address, Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getDataByAddress(address);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取指定地址数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定设备和地址的PLC数据
     * @param deviceId 设备ID
     * @param address Modbus地址
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getDataByDeviceAndAddress(final int deviceId, final String address, 
                                         Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getDataByDeviceAndAddress(deviceId, address);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取指定设备和地址数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定类型的PLC数据
     * @param type 数据类型
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getDataByType(final String type, Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getDataByType(type);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取指定类型数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取最新的PLC数据
     * @param address Modbus地址
     * @param successCallback 成功回调，返回数据实体
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getLatestDataByAddress(final String address, Consumer<PlcDataEntity> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                PlcDataEntity data = plcDataDao.getLatestDataByAddress(address);
                if (data != null) {
                    if (successCallback != null) {
                        successCallback.accept(data);
                    }
                } else {
                    String errorMsg = "未找到指定地址的数据: " + address;
                    Log.e(TAG, errorMsg);
                    if (errorCallback != null) {
                        errorCallback.accept(errorMsg);
                    }
                }
            } catch (Exception e) {
                String errorMsg = "获取最新数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 获取指定设备的最新PLC数据
     * @param deviceId 设备ID
     * @param address Modbus地址
     * @param successCallback 成功回调，返回数据实体
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getLatestDataByDeviceAndAddress(final int deviceId, final String address, 
                                               Consumer<PlcDataEntity> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                PlcDataEntity data = plcDataDao.getLatestDataByDeviceAndAddress(deviceId, address);
                if (data != null) {
                    if (successCallback != null) {
                        successCallback.accept(data);
                    }
                } else {
                    String errorMsg = "未找到指定设备和地址的数据: [设备ID=" + deviceId + ", 地址=" + address + "]";
                    Log.e(TAG, errorMsg);
                    if (errorCallback != null) {
                        errorCallback.accept(errorMsg);
                    }
                }
            } catch (Exception e) {
                String errorMsg = "获取设备最新数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 清理旧数据
     * @param timestamp 时间戳，删除此时间之前的数据
     * @param onComplete 操作完成回调
     * @param onError 错误回调
     */
    public void cleanupOldData(final long timestamp, Runnable onComplete, Consumer<String> onError) {
        executor.execute(() -> {
            try {
                plcDataDao.deleteDataBefore(timestamp);
                Log.d(TAG, "已清理" + timestamp + "之前的旧数据");
                if (onComplete != null) {
                    onComplete.run();
                }
            } catch (Exception e) {
                String errorMsg = "清理旧数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (onError != null) {
                    onError.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 清理指定设备的数据
     * @param deviceId 设备ID
     * @param onComplete 操作完成回调
     * @param onError 错误回调
     */
    public void cleanupDeviceData(final int deviceId, Runnable onComplete, Consumer<String> onError) {
        executor.execute(() -> {
            try {
                plcDataDao.deleteDataByDeviceId(deviceId);
                Log.d(TAG, "已清理设备ID " + deviceId + " 的数据");
                if (onComplete != null) {
                    onComplete.run();
                }
            } catch (Exception e) {
                String errorMsg = "清理设备数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (onError != null) {
                    onError.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 删除所有数据
     * @param onComplete 操作完成回调
     * @param onError 错误回调
     */
    public void deleteAllData(Runnable onComplete, Consumer<String> onError) {
        executor.execute(() -> {
            try {
                plcDataDao.deleteAll();
                Log.d(TAG, "已删除所有数据");
                if (onComplete != null) {
                    onComplete.run();
                }
            } catch (Exception e) {
                String errorMsg = "删除所有数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (onError != null) {
                    onError.accept(errorMsg);
                }
            }
        });
    }
    
    /**
     * 删除所有数据（无回调）
     */
    public void deleteAllData() {
        deleteAllData(null, null);
    }
    
    /**
     * 获取历史数据
     * @param deviceId 设备ID
     * @param address Modbus地址
     * @param startTime 开始时间戳
     * @param endTime 结束时间戳
     * @param limit 限制返回记录数
     * @param successCallback 成功回调，返回数据列表
     * @param errorCallback 错误回调，返回错误信息
     */
    public void getHistoryData(final int deviceId, final String address, final long startTime, final long endTime, 
                              final int limit, Consumer<List<PlcDataEntity>> successCallback, Consumer<String> errorCallback) {
        executor.execute(() -> {
            try {
                List<PlcDataEntity> dataList = plcDataDao.getHistoryData(deviceId, address, startTime, endTime, limit);
                if (successCallback != null) {
                    successCallback.accept(dataList);
                }
            } catch (Exception e) {
                String errorMsg = "获取历史数据失败: " + e.getMessage();
                Log.e(TAG, errorMsg, e);
                if (errorCallback != null) {
                    errorCallback.accept(errorMsg);
                }
            }
        });
    }
} 